<?php
namespace App\Libs\Common;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class RsaUtil extends Controller
{ 

    public function test()
    {
        header("Content-type: text/html; charset=utf-8");
        
        $res=self::rsaEncrypt('abc','./Public/rsa/lvyue_public_key.pem');

        echo $res;
    }


    public function test2()
    {   

        $str="EbqeMAZSqkGtkL/ps49GhaXzWUTZvl0TBU80uQvl99Kthgx1pCro81XLtrFNmKgQMREzWMolldKaetxYEvHw9cyskSyTHjLnOOg3CwT235dgM90jjDl9PHOZE7l3IrsRysO7c71JMfa0LAScbf19UaZUW1AfuilktQ1kyDN1bAY=";

        $str2="PKEs4Ho8/Xf3ettiVmOzepMOaQv7gmwXwkZovthXllJtuMAbkt2VZC/1OOVp2LKYzbOat0gqtn7wDMvtlw4wvfKQ+apQ0seoKsviEXUvisHrbGOD8bhmgEdHyWjT5iRItRdd0jMSPfcTHnJ6wCkRRZjSzMCdUmjMPm+7qgJ0zzE=";
        
        $res=self::rsaDecrypt($str2,'./Public/rsa/lvyue_private_key.pem');

        var_dump($res);
    }


    /*
    *    返回顺序拼接好的参数
    *    @params        params(array)        需要拼接的参数
    *    @params        urlencode(boolean)   是否需要对值进行处理    
    */
    public function paramsString($params=null,$urlencode=true) 
    {   
        if ($params == null) $params=$_REQUEST;

        ksort($params);

        $str = "";

        foreach ($params as $k => $v) 
        {  

            if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) 
            {
               if ($urlencode) 
               {
                   $str.="$k=".urlencode($v).'&';
               }else{
                   $str.="$k=".$v.'&';
               }
            }
        }

        return trim($str,'&');
    }


    /**
     * DES加密 - 提交数据
     * @param $str
     * @param $key
     * @return string
     */
    public function des_encrypt($str, $key)  {
        $block = mcrypt_get_block_size('des', 'ecb');
        $pad = $block - (strlen($str) % $block);
        $str .= str_repeat(chr($pad), $pad);
        $str = mcrypt_encrypt(MCRYPT_DES, $key, $str, MCRYPT_MODE_ECB);
        return base64_encode($str);
    }

    /**
     * DES解密 - 返回数据
     * @param $str
     * @param $key
     * @return string
     */
    public function des_decrypt($str, $key) {
        $str = base64_decode($str);
        $str = mcrypt_decrypt(MCRYPT_DES, $key, $str, MCRYPT_MODE_ECB);
        $block = mcrypt_get_block_size('des', 'ecb');
        $pad = ord($str[($len = strlen($str)) - 1]);
        return substr($str, 0, strlen($str) - $pad);
    }

    /**
     * 加签
     * @param $data 要加签的数据
     * @param $privateKeyFilePath 私钥文件路径
     * @return string 签名
     */
    public static function sign($data, $privateKeyFilePath) {

        $priKey = file_get_contents($privateKeyFilePath);
        $res = openssl_get_privatekey($priKey);
        openssl_sign($data, $sign, $res,OPENSSL_ALGO_SHA1);
        openssl_free_key($res);
        $sign = base64_encode($sign);
        return $sign;
    }

    

    /**
     * 验签
     * @param $data 用来加签的数据
     * @param $sign 加签后的结果
     * @param $rsaPublicKeyFilePath 公钥文件路径
     * @return bool 验签是否成功
     */
    public static function verify($data, $sign, $rsaPublicKeyFilePath) {
        //读取公钥文件
        $pubKey = file_get_contents($rsaPublicKeyFilePath);

        //转换为openssl格式密钥
        $res = openssl_get_publickey($pubKey);

        //调用openssl内置方法验签，返回bool值
        $result = (bool)openssl_verify($data, base64_decode($sign), $res);

        //释放资源
        openssl_free_key($res);

        return $result;
    }


    /**
     * rsa加密
     * @param $data 要加密的数据
     * @param $pubKeyFilePath 公钥文件路径
     * @return string 加密后的密文
     */
    public static function rsaEncrypt($data, $pubKeyFilePath){
        //读取公钥文件
        $pubKey = file_get_contents($pubKeyFilePath);

        //转换为openssl格式密钥
        $res = openssl_get_publickey($pubKey);

        $maxlength = self::getMaxEncryptBlockSize($res);
        $output='';
        while(strlen($data)){
            $input= substr($data,0,$maxlength);
            $data=substr($data,$maxlength);
            openssl_public_encrypt($input,$encrypted,$pubKey);
            $output.= $encrypted;
        }
        
        $encryptedData =  base64_encode($output);
        return $encryptedData;
    }

    /**
     * 解密
     * @param $data 要解密的数据
     * @param $privateKeyFilePath 私钥文件路径
     * @return string 解密后的明文
     */
    public static function rsaDecrypt($data, $privateKeyFilePath){
        //读取私钥文件
        $priKey = file_get_contents($privateKeyFilePath);
        //转换为openssl格式密钥
        $res = openssl_get_privatekey($priKey);
        $data = base64_decode($data);
        $maxlength = self::getMaxDecryptBlockSize($res);
        $output='';
        while(strlen($data)){
            $input = substr($data,0,$maxlength);
            $data = substr($data,$maxlength);
            openssl_private_decrypt($input,$out,$res);
            $output.=$out;
        }
    
        return $output;
    }

    /**
     *根据key的内容获取最大加密lock的大小，兼容各种长度的rsa keysize（比如1024,2048）
     * 对于1024长度的RSA Key，返回值为117
     * @param $keyRes
     * @return float
     */
    public static function getMaxEncryptBlockSize($keyRes){
        $keyDetail = openssl_pkey_get_details($keyRes);
        $modulusSize = $keyDetail['bits'];
        return $modulusSize/8 - 11;
    }

    /**
     * 根据key的内容获取最大解密block的大小，兼容各种长度的rsa keysize（比如1024,2048）
     * 对于1024长度的RSA Key，返回值为128
     * @param $keyRes
     * @return float
     */
    public static function getMaxDecryptBlockSize($keyRes){
        $keyDetail = openssl_pkey_get_details($keyRes);
        $modulusSize = $keyDetail['bits'];
        return $modulusSize/8;
    }


     /* 校验$value是否非空
     *  if not set ,return true;
     *    if is null , return true;
     **/
    protected function checkEmpty($value) 
    {
        if (!isset($value))
            return true;
        if ($value === null)
            return true;
        if (trim($value) === "")
            return true;

        return false;
    }


}